home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr50 / bcc101.zip / XPRINT.ZIP / XPRINT.ASM next >
Assembly Source File  |  1993-03-20  |  17KB  |  423 lines

  1. comment|
  2. This source code is for QB NEAR STRINGS only. MASM 5.1 compatible.
  3. Written by Brian McLaughlin. Released into the public domain 3/5/93.
  4.  
  5. WARNING: Before *ANY* of the working routines in this group can be called
  6. safely from your program, the routine XInit must be called once. (No
  7. further calls to XInit are needed.)
  8.  
  9. XInit sets several internal variables and default behaviors. It sets the
  10. active display page and visible display page to zero. It also detects if a
  11. CGA monitor is in use and sets a flag to suppress snow. This behavior can
  12. be overridden by setting the IgnoreSnow% variable to a non-zero value.  In
  13. that case the presence of a CGA is ignored and fast printing is used.
  14. XInit also sets the initial viewport to cover the entire screen (25x80),
  15. and sets the default colors to white on black. It puts the cursor in the
  16. first column of the row where it finds the cursor.  The only display size
  17. supported by these routines is 25x80. (The 43/50 line options are not
  18. supported.)
  19.  
  20. XPrint prints only strings. Numbers MUST be converted to strings before
  21. printing them (by using STR$ or a similar routine). XPrint uses the current
  22. colors defined by XColor. It prints at the current cursor position.  When
  23. the variable NumScrolls% is set to 0, XPrint will behave like PRINT with a
  24. trailing semicolon, and the cursor will not be advanced beyond the space
  25. following the end of the printed string. When NumScrolls% is set to 1,
  26. Xprint will behave like PRINT with no semicolon, and the cursor will be
  27. advanced to the beginning of the next line. If NumScrolls% is greater than
  28. 1, the cursor will be advanced until that number of carriage returns and
  29. line feeds are performed, much like PRINT: PRINT: PRINT.  Scrolling is
  30. automatic when printing on the last line of the viewport.
  31.  
  32. XViewPort is similar to VIEW PRINT, except it allows column as well as row
  33. arguments. Screen coordinates follow BASIC convention, so that the upper
  34. left corner is 1,1 and the lower right is 25,80. If it is passed an illegal
  35. argument (for example a column or row less than 1 or a top row beneath the
  36. bottom row) then it defaults to a viewport consisting of the entire screen
  37. (25x80). When XViewPort is called and the cursor is detected outside the
  38. viewport's boundaries then the cursor will be brought into the viewport and
  39. placed at the top left corner, no matter where it was before.
  40.  
  41. XLocate works a lot like LOCATE X%,Y%. You must always pass both the row
  42. and column arguments. When passed an illegal coordinate (outside the
  43. current viewport) XLocate will place the cursor as near to the requested
  44. position as it can, while keeping it within the viewport. IMPORTANT: Row
  45. and column arguments are numbered relative to the whole screen, so that the
  46. position 1,1 is ALWAYS the top left corner of the screen, which is NOT
  47. necessarily the top left corner of the current viewport. If the defined
  48. viewport does not include screen position 1,1 then those coordinates are
  49. illegal.
  50.  
  51. XCursorOn turns the cursor on (when it is off) and controls its shape.  It
  52. accepts one argument, telling it whether the cursor should appear as a
  53. block (non-zero value) or an underline (zero value). XCursorOff makes the
  54. cursor invisible, if it is visible.
  55.  
  56. XColor sets the current foreground and background colors. It follows the
  57. QuickBASIC conventions: allowable background colors are 0-7. Foreground
  58. colors of 0-7 are normal, 8-15 are high intensity, and blinking is
  59. obtained by adding 16 to the desired foreground color (16-31).
  60.  
  61. XCls clears the currently defined viewport to the current colors and puts
  62. the cursor in the top left corner.
  63.  
  64. XCsrLin% returns the current cursor row, like CSRLIN. XPos% returns the
  65. current cursor column, like POS(0).
  66.  
  67. end comment|
  68.  
  69. .MODEL MEDIUM, BASIC
  70. .DATA
  71.         ViewportTopRow        DB 0          ; initial viewport is whole screen
  72.         ViewportTopCol        DB 0
  73.         ViewportBotRow        DB 24         ; 0-24 = 25 rows total
  74.         ViewportBotCol        DB 79         ; 0-79 = 80 columns total
  75.         ColorAttr             DB 7          ; default to white on black
  76.         CursorRow             DB 0          ; zero-based coordinate
  77.         CursorCol             DB 0          ; zero-based coordinate
  78.         SnowFlag              DB 0          ; default = no snow suppression
  79.         VidPort               DW 03BAh      ; monochrome port default
  80.         VidSeg                DW 0B000h     ; monochrome segment default
  81.         VidOffset             DW 0
  82. .CODE
  83.    ; these variables are stored in code segment, rather than DGROUP
  84.         CursorTopLine         DB 0Bh        ; monochrome default cursor
  85.         CursorEndLine         DB 0Ch        ; monochrome default cursor
  86.  
  87. XInit PROC FAR, IgnoreSnow:WORD
  88.         Mov AX, 0500h           ; set display page to 0
  89.         Int 10h                 ; using the BIOS
  90.         Xor BH, BH
  91.         Mov AH, 03h             ; discover current cursor row
  92.         Int 10h                 ; using the BIOS
  93.         Mov CursorRow, DH       ; and save that row
  94.         Call $SetVideoOffset    ; and calculate new offset
  95.         Xor AX, AX
  96.         Mov ES, AX
  97.         Mov AX, ES:[0463h]      ; get the CRT port address
  98.         Cmp AL, 0B4h            ; and look at it
  99.         Je  GotMon              ; it's mono, the default
  100.         Mov VidSeg, 0B800h      ; otherwise, set up for color monitor
  101.         Mov VidPort, 03DAh      ;
  102.         Mov CS:CursorTopLine, 06h
  103.         Mov CS:CursorEndLine, 07h
  104.         Mov BL, 10h             ; now let's look for EGA/VGA installed
  105.         Mov AH, 12h             ; using BIOS service 12
  106.         Int 10h                 ; call BIOS
  107.         Cmp BL, 10h             ; if BL changes there's an EGA/VGA
  108.         Jne GotMon              ; and we assume EGA/VGA
  109.         Mov BX, IgnoreSnow      ; so, did the user abort snow suppresion?
  110.         Mov AX, [BX]            ; let's see!
  111.         Or  AX, AX              ; were we passed a zero?
  112.         Jz  GotMon              ; a non-zero means *don't* suppress snow
  113.         Mov SnowFlag, 1         ; otherwise, assume snow problems
  114. GotMon:
  115.         Ret
  116. XInit ENDP
  117.  
  118. XPrint PROC FAR USES ES DI SI, String:WORD, NumScrolls:WORD
  119.         Mov DI, String          ; get address of descriptor
  120.         Mov CX, [DI]            ; get string's length in bytes
  121.         Jcxz NullString         ; String was null
  122.         Mov SI, [DI+2]          ;DS:SI points to String in memory
  123.         Mov AX, VidSeg          ; can't put VidSeg into ES directly
  124.         Mov ES, AX              ;ES = video segment
  125.         Mov DI, VidOffset       ;ES:DI points to current cursor position
  126.         Mov AH, ColorAttr       ; AL holds the character, AH the attribute
  127.         Mov DX, VidPort         ; We'll need this for snow suppression
  128.         Mov BH, SnowFlag        ; get snow flag
  129.         Mov BL, CursorCol
  130.         Cld                     ; clear direction flag for forward write
  131. WriteCharLoop:
  132.         Or BH, BH               ; check for snow flag
  133.         Jz FastWrite
  134. WaitHere:
  135.         In AL, DX               ; get video status byte into AL
  136.         Test AL, 1              ; test the retrace bit
  137.         Jnz WaitHere            ; wait until it zeros
  138.         Cli                     ; disable interrupts
  139. WaitAgain:
  140.         In AL, DX               ; test again
  141.         Test AL, 1
  142.         Jz WaitAgain
  143. FastWrite:
  144.         Lodsb                   ; loads char into AL
  145.         Stosw                   ; put char+attribute into video buffer
  146.         Sti                     ; enable interrupts again
  147.         Inc BL                  ; keep track of cursor position
  148.         Mov AL, ViewportBotCol  ; AL is only temporarily available
  149.         Cmp AL, BL              ; is cursor inside viewport boundary
  150.         Jae InBounds
  151.         Call $ResetCursor       ; reset cursor to first col, scroll if need be
  152.         Mov DI, VidOffset       ; reset DI to correct offset
  153.         Mov BL, CursorCol       ; reset BL to new CursorCol
  154. InBounds:
  155.         Loop WriteCharLoop
  156.         Mov CursorCol, BL       ; save final cursor column
  157. NullString:
  158.         Mov SI, NumScrolls      ; take care of NumScrolls scrolling now
  159.         Mov CX, [SI]            ; get the value into CX
  160.         Jcxz NoCRLF
  161. CRLoop:
  162.         Call $ResetCursor       ; let this PROC do the work
  163.         Loop CRLoop             ; however many times its needed
  164. NoCRLF:
  165.         Call $SetCursorPosition ; set the cursor where desired
  166.         Call $SetVideoOffset    ; calculate offset where cursor ended up
  167.         Ret
  168. XPrint ENDP
  169.  
  170.  
  171. XCsrLin PROC FAR
  172.         Mov AL, CursorRow       ; put the value in AL
  173.         Inc AL                  ; revert to 1-based coordinates
  174.         Cbw
  175.         Ret
  176. XCsrLin ENDP
  177.  
  178.  
  179. Xpos PROC FAR
  180.         Mov AL, CursorCol       ; put the value in AL
  181.         Inc AL                  ; return a 1-based coordinate
  182.         Cbw
  183.         Ret
  184. XPos ENDP
  185.  
  186.  
  187. XCls PROC FAR
  188.         Xor AL, AL
  189.         Call $ScrollWin         ; sending zero in AL clears the screen
  190.         Mov AL, ViewportTopRow
  191.         Mov CursorRow, AL
  192.         Mov AL, ViewportTopCol
  193.         Mov CursorCol, AL
  194.         Call $SetCursorPosition ; move cursor to top corner
  195.         Call $SetVideoOffset    ; recalculate video offset
  196.         Ret
  197. XCls ENDP
  198.  
  199.  
  200. XLocate PROC, Row:WORD, Col:WORD
  201.         Mov BX, Row
  202.         Mov AL, Byte Ptr [BX]
  203.         Dec AL                     ; convert to zero-based coordinates
  204.         Cmp AL, ViewportTopRow
  205.         Jl  RowTooLow
  206.         Cmp AL, ViewPortBotRow
  207.         Jg  RowTooHigh
  208. RowRight:
  209.         Mov CursorRow, AL          ; save row coordinate
  210.         Mov BX, Col
  211.         Mov AL, Byte Ptr [BX]
  212.         Dec AL                     ; convert to zero-based coordinates
  213.         Cmp AL, ViewportTopCol
  214.         Jl  ColTooLow
  215.         Cmp AL, ViewportBotCol
  216.         Jg  ColTooHigh
  217. ColRight:
  218.         Mov CursorCol, AL          ; save column coordinate
  219.         Call $SetCursorPosition    ; move cursor into place
  220.         Call $SetVideoOffset       ; recalculate current offset
  221.         Ret
  222. RowTooLow:
  223.         Mov AL, ViewportTopRow     ; keep row in viewport boundary
  224.         Jmp SHORT RowRight
  225. RowTooHigh:
  226.         Mov AL, ViewportBotRow     ; keep row in viewport boundary
  227.         Jmp SHORT RowRight
  228. ColTooLow:
  229.         Mov AL, ViewportTopCol     ; keep column in viewport boundary
  230.         Jmp SHORT ColRight
  231. ColTooHigh:
  232.         Mov AL, ViewportBotCol     ; keep column in viewport boundary
  233.         Jmp SHORT ColRight
  234. XLocate ENDP
  235.  
  236.  
  237. XColor PROC FAR, Fore:WORD, Back:WORD
  238.         Xor DL, DL              ; put a zero into DL
  239.         Mov BX, Fore            ; get address of Fore
  240.         Mov AX, [BX]            ; put FG color into bits 0-4 of AX
  241.         Test AX, 10h            ; is bit 4 set? (blinking requested?)
  242.         Jnz SetBlink            ; if it is, then go arrange for blink
  243. SetColor:
  244.         Mov BX, Back
  245.         Mov AH, Byte Ptr [BX]   ; put BG color into AH
  246.         And AH, 7               ; only keep bits 0-2
  247.         Mov CL, 4
  248.         Shl AH, CL              ; shift bits 0-2 into bits 4-6
  249.         Or  AL, AH              ; introduce BG value into bits 4-6 of AL
  250.         Or  AL, DL              ; sets bit 7 of AL, if blinking requested
  251.         Mov ColorAttr, AL       ; save the result internally
  252.         Ret
  253. SetBlink:
  254.         And AL, 0Fh             ; keep bits 0-3 of AL, discard 4-7
  255.         Mov DL, 0F0h            ; set bit 7 in DL
  256.         Jmp SHORT SetColor
  257. XColor ENDP
  258.  
  259.  
  260. XViewPort PROC FAR, TopRow:WORD, TopCol:WORD, BotRow:WORD, BotCol:WORD
  261.         Mov BX, TopRow          ; get address
  262.         Mov AL, Byte Ptr [BX]   ; get value
  263.         Dec AL                  ; convert to zero-based coordinates
  264.         Cmp AL, 0
  265.         Jl  Abort               ; signed comparisons throughout
  266.         Cmp AL, 24
  267.         Jg  Abort
  268.         Mov DL, AL              ; DL = TopRow
  269.         Mov BX, TopCol          ; get address
  270.         Mov AL, Byte Ptr [BX]   ; get value
  271.         Dec AL                  ; convert to zero-based coordinates
  272.         Cmp AL, 0
  273.         Jl  Abort               ; trap an illegal value
  274.         Cmp AL, 79
  275.         Jg  Abort               ; trap an illegal value
  276.         Mov DH, AL              ; DH = TopCol
  277.         Mov BX, BotRow          ; get address
  278.         Mov AL, Byte Ptr [BX]   ; get value
  279.         Dec AL                  ; convert to zero-based coordinates
  280.         Cmp AL, DL              ; compare to TopRow
  281.         Jl  Abort               ; trap an illegal value
  282.         Cmp AL, 24
  283.         Jg  Abort               ; trap an illegal value
  284.         Mov CL, AL              ; CL = BotRow
  285.         Mov BX, BotCol          ; get address
  286.         Mov AL, Byte Ptr [BX]   ; get value
  287.         Dec AL                  ; convert to zero-based coordinates
  288.         Cmp AL, DH              ; compare to TopCol
  289.         Jl  Abort               ; trap an illegal value
  290.         Cmp AL, 79
  291.         Jg  Abort               ; trap an illegal value
  292.         Cmp CursorRow, DL       ; is the cursor inside the viewport?
  293.         Jb  PutCursInside       ; if not, move it in
  294.         Cmp CursorRow, CL
  295.         Ja  PutCursInside       ; if not, move it in
  296.         Cmp CursorCol, DH
  297.         Jb  PutCursInside       ; if not, move it in
  298.         Cmp CursorCol, AL
  299.         Ja  PutCursInside       ; if not, move it in
  300. SaveVars:
  301.         Mov ViewportTopRow, DL
  302.         Mov ViewportTopCol, DH
  303.         Mov ViewportBotRow, CL
  304.         Mov ViewportBotCol, AL
  305.         Ret
  306. Abort:
  307.         Xor DX, DX              ; set top corner to 0, 0
  308.         Mov CL, 24              ; set bottom corner to 24, 79
  309.         Mov AL, 79
  310.         Jmp SHORT SaveVars
  311. PutCursInside:
  312.         Mov CursorRow, DL       ; move the cursor to top left
  313.         Mov CursorCol, DH
  314.         Call $SetCursorPosition ; make it all official
  315.         Call $SetVideoOffset
  316.         Jmp SHORT SaveVars
  317. XViewPort ENDP
  318.  
  319.  
  320. XCursorOn PROC FAR, BigFlag:WORD
  321.         Mov CL, CS:CursorEndLine
  322.         Mov BX, BigFlag
  323.         Mov AX, [BX]
  324.         Or  AX, AX
  325.         Jnz Big
  326.         Mov CH, CS:CursorTopLine   ;makes an underline cursor
  327. Ready:
  328.         Mov AH, 01h
  329.         Int 10h
  330.         Ret
  331. Big:
  332.         Xor CH, CH                 ; change top line to zero
  333.         Jmp SHORT Ready            ; for a big cursor
  334. XCursorOn ENDP
  335.  
  336.  
  337. XCursorOff PROC FAR
  338.         Mov CX, 2000h           ; should force invisible cursor
  339.         Mov AH, 01h
  340.         Int 10h
  341.         Ret
  342. XCursorOff ENDP
  343.  
  344.  
  345. $ResetCursor PROC NEAR
  346.         Push AX                 ; preserve AX to free a working register
  347.         Mov AL, CursorRow       ; get what row we're in
  348.         Mov AH, ViewportBotRow  ; get the bottom row of text window
  349.         Cmp AL, AH              ; see if they match
  350.         Je  InBotRow            ; if they do, we need to scroll a line
  351.         Inc CursorRow           ; if not, show we moved a row down
  352. ResumeReset:
  353.         Mov AL, ViewportTopCol  ; and adjust column to leftmost one
  354.         Mov CursorCol, AL
  355.         Call $SetVideoOffset    ; recalculate VidOffset
  356.         Pop AX                  ; restore AX to previous value
  357.         Ret
  358. InBotRow:
  359.         Mov AL, 1               ; ask for a one-line scroll
  360.         Call $ScrollWin         ; do it
  361.         Jmp SHORT ResumeReset   ; go back to do the rest
  362. $ResetCursor ENDP
  363.  
  364.  
  365. $ScrollWin PROC NEAR       ;call with AL = lines to scroll (0 means clear it)
  366.         Push AX
  367.         Push BX
  368.         Push CX
  369.         Push DX
  370.         Mov AH, 06h
  371.         Mov BH, ColorAttr
  372.         Mov CH, ViewPortTopRow
  373.         Mov CL, ViewPortTopCol
  374.         Mov DH, ViewPortBotRow
  375.         Mov DL, ViewPortBotCol
  376.         Int 10h
  377.         Pop DX
  378.         Pop CX
  379.         Pop BX
  380.         Pop AX
  381.         Ret
  382. $ScrollWin ENDP
  383.  
  384.  
  385. $SetCursorPosition PROC NEAR   ;call this with CursorRow/CursorCol set properly
  386.         Push DX
  387.         Push AX
  388.         Xor BH, BH              ; display page zero
  389.         Mov DH, CursorRow
  390.         Mov DL, CursorCol
  391.         Mov AH, 02h
  392.         Int 10h
  393.         Pop AX
  394.         Pop DX
  395.         Ret
  396. $SetCursorPosition ENDP
  397.  
  398.  
  399. $SetVideoOffset PROC NEAR    ;call with CursorRow/CursorCol set properly
  400.         Push AX
  401.         Push BX
  402.         Push CX
  403.         Xor AH, AH
  404.         Xor BH, BH
  405.         Mov AL, CursorRow       ; what row are we at?
  406.         Mov BL, AL              ; make a second copy
  407.         Mov CL, 5
  408.         Shl AX, CL              ; multiply row * 32 into AX
  409.         Mov CL, 7
  410.         Shl BX, CL              ; multiply row * 128 into BX
  411.         Add BX, AX              ; BX = row * 160 bytes (each char is 2)
  412.         Xor AH, AH
  413.         Mov AL, CursorCol
  414.         Shl AX, 1               ; AX = col * 2
  415.         Add AX, BX              ; AX = correct offset in video memory
  416.         Mov VidOffset, AX       ; save it
  417.         Pop CX
  418.         Pop BX
  419.         Pop AX
  420.         Ret
  421. $SetVideoOffset ENDP
  422.            END
  423.